<html>
    <head>
        <style>
            body {
                padding: 0;
                margin: 0;
            }

            #box-a {
                position: absolute;
                top: 0px;
                left: 0px;
                width: 100px;
                height: 100px;
                background-color: #00cc88;
            }

            #box-b {
                position: absolute;
                top: 100px;
                left: 100px;
                width: 100px;
                height: 100px;
                background-color: #09f;
            }

            #mid-a,
            #mid-b {
                position: relative;
                width: 50px;
                height: 50px;
            }

            #child-a {
                position: absolute;
                top: 50px;
                width: 50px;
                height: 50px;
                background-color: #09f;
            }

            #child-b {
                position: absolute;
                top: 100px;
                width: 50px;
                height: 50px;
                background-color: #00cc88;
            }

            #child-a.moved {
                top: 100px;
            }

            #trigger-overflow {
                width: 1px;
                height: 1px;
                position: absolute;
                top: 2000px;
                left: 2000px;
            }

            [data-layout-correct="false"] {
                background: #dd1144 !important;
                opacity: 0.5;
            }
        </style>
    </head>
    <body>
        <div id="box-a">
            <div id="mid-a"><div id="child-a"></div></div>
        </div>
        <div id="trigger-overflow"></div>

        <script type="module" src="/src/imports/projection.js"></script>
        <script type="module" src="/src/imports/script-assert.js"></script>
        <script type="module" src="/src/imports/script-animate.js"></script>
        <script type="module">
            const { createNode } = window.Animate
            const {
                matchViewportBox,
                matchVisibility,
                matchOpacity,
                matchBorderRadius,
            } = window.Assert
            const { frame } = window.Projection

            const box = document.getElementById("box-a")
            const boxProjection = createNode(box, undefined, {
                layoutId: "a",
                crossfade: true,
            })
            const mid = document.getElementById("mid-a")
            const midProjection = createNode(mid, boxProjection, {
                layoutId: "container",
                crossfade: true,
            })
            const child = document.getElementById("child-a")
            const childProjection = createNode(child, midProjection, {
                layoutId: "b",
                crossfade: true,
            })

            boxProjection.willUpdate()
            midProjection.willUpdate()
            childProjection.willUpdate()

            // mount & promote B
            const newBox = document.createElement("div")
            newBox.id = "box-b"
            document.body.appendChild(newBox)
            const newBoxProjection = createNode(newBox, undefined, {
                layoutId: "a",
                crossfade: true,
            })

            const newMid = document.createElement("div")
            newMid.id = "mid-b"
            newBox.appendChild(newMid)

            const newMidProjection = createNode(newMid, newBoxProjection, {
                layoutId: "container",
                crossfade: true,
            })

            const newChild = document.createElement("div")
            newChild.id = "child-b"
            newMid.appendChild(newChild)
            const newChildProjection = createNode(newChild, newMidProjection, {
                layoutId: "b",
                crossfade: true,
            })

            const newBoxOrigin = newBox.getBoundingClientRect()
            const newChildOrigin = newChild.getBoundingClientRect()

            newBoxProjection.root.didUpdate()

            // promote A and skip layout updates
            boxProjection.root.blockUpdate()

            boxProjection.willUpdate()
            midProjection.willUpdate()
            childProjection.willUpdate()
            newBoxProjection.willUpdate()
            newMidProjection.willUpdate()
            newChildProjection.willUpdate()

            boxProjection.promote({ needsReset: true })
            midProjection.promote({ needsReset: true })
            childProjection.promote({ needsReset: true })

            childProjection.root.didUpdate()

            frame.postRender(() => {
                // only update child layout
                childProjection.willUpdate()

                child.classList.add("moved")

                childProjection.root.didUpdate()

                frame.postRender(() => {
                    const midChildBox = {
                        left: 0,
                        right: 50,
                        top: 75,
                        bottom: 125,
                    }

                    matchViewportBox(child, midChildBox)
                })
            })
        </script>
    </body>
</html>
